package benchmark;
import java.util.*;

import utils.ArgumentParsingException;
import utils.MissingArgumentException;


public abstract class AbstractBenchmark {
	
	Hashtable<String, Long> argTable;
	Hashtable<String, String> argReadme;

	private final static String WARMUP_CYCLES = "wcycles";
	private final static String WARMUP_TIMES = "wtimes";
	private final static String BENCHMARK_CYCLES = "bcycles";

	public AbstractBenchmark(String[] args) throws Exception {
		argReadme = new Hashtable<String, String>();
		argReadme.put(WARMUP_CYCLES, "Iteration times for JVM warmup.");
		argReadme.put(WARMUP_TIMES, "Warmup Times.");
		argReadme.put(BENCHMARK_CYCLES, "Iteration times for main testing.");
		
		argTable = parseArgs(args);
		
	}
	
	/**
	 * @param args: Arguments that need to be parsed.
	 * @return Key & value pair of the arguments.
	 * @throws ArgumentParsingException Format error.
	 */
	public static Hashtable<String, Long> parseArgs(String[] args) throws ArgumentParsingException {
		Hashtable<String, Long> argTable = new Hashtable<String, Long>();
		for (String a : args) {
			String[] kv = a.split("=");
			if (kv.length != 2) {
				throw new ArgumentParsingException(a);
			}
			String k = kv[0];
			long v = -1;
			try {
				v = Long.parseLong(kv[1]);
			} catch (NumberFormatException e) {
				
			}
			argTable.put(k, v);
		}
		return argTable;
	}
	
	protected long getArg(String argName) throws MissingArgumentException {
		Long arg = argTable.get(argName);
		if (arg == null) {
			throw new MissingArgumentException(this);
		}
		return arg;
	}
		
	abstract protected void benchmark(String name, long cycles) throws Exception;
	
	
	public void run() throws Exception {
		// warmup
		long warmupTime = getArg(WARMUP_TIMES);
		while (warmupTime -- > 0) {
			benchmark("warmup" + Long.toString(warmupTime), getArg(WARMUP_CYCLES));			
		}
		
//		Thread.sleep(1000);

		// benchmark
		benchmark("benchmark", getArg(BENCHMARK_CYCLES));
	}
	
	
	public String Readme() {
		return argReadme.toString();
	}
}
